import cell from "../../word/cell";
import battlefield from "../battle/battlefield";
import buff_item from "../buff/buff_item";
import buffs from "../buff/buffs";
import { SKILL, SK_data, battle_logNum } from "../skill/SK_active";
import app, { xlsxCfgNames } from "../../../app";
import { group, face_Points, SK_type, bar, EffectType, EffectCondition, BuffEffect } from "../../../shared/interface";
import { equip } from "../equip/equip";
import { _Cls_Points } from "./att/_Points";
import SK_func from "../skill/SK_func";
import { _Cls_Att } from "./att/_Att";
import { Tpl_panel_job, Tpl_panel_talent, template } from "../../../shared/master/MsgAction";
import { logger } from "../../server/logger";
import { pet } from "./pet";
import body_tool from "./body_tool";
import { player } from "./player";
import manage_word from "../../../master/model/manage/manage_word";

/**
 * 创建单位基础数据
 */
export interface CreateBody_base {
    leve: number
    name: string
    style_id: string
    Points: face_Points
    sk_actives: SK_data[]
    /**
     * 天赋ID
     */
    Job: string
    Job_leve: number
    /**
     * 血统ID
     */
    Talent: string
    Talent_leve: number
}
export class baseBody {
    icon: string = '🧙'
    name: string = `轮回者#${app.random(1, 99)}`;
    /**
 * 单位样式ID
 */
    style_id: string = '1'

    leve: bar = {
        num: 1,
        now: 0,
        max: 100
    }

    uuid: string = app.v4();
    /**
     * 当前生命值
     */
    Hp_now: number = 100;
    /**
     * 当前蓝量
     */
    Mp_now: number = 100;
    /**
     * 最后活跃时间
     */
    _lastActiveTime: number = Date.now();
    /**
     * 天赋属性
     */
    Talent: _Cls_Points = new _Cls_Points();
    Talent_id: string = '1';
    Talent_leve: bar = {
        num: 1,
        now: 0,
        max: 10000
    }
    /**
     * 血统
     */
    Job: _Cls_Points = new _Cls_Points();
    Job_id: string = '1';
    Job_leve: bar = {
        num: 1,
        now: 0,
        max: 10000
    }
    _bodyType: string = 'enemy';
    /**
    * 动态生成属性
    */
    _attributes: _Cls_Att = new _Cls_Att();
    private _group: group = group.主场;
    private _buffs: buffs = new buffs();
    /**
     * 当前所在格子
     */
    _position!: cell | undefined;
    private _battleArea: battlefield | undefined;
    /**
     * 是否已经决策了下一回合的技能
     */
    private _hasDecided: number = -1;
    private _selectSkill: string = '';
    private _init: boolean = false;

    get nickName(): string {
        return `${this.icon}${this.name}`
    }


    /**
 * 属性点 - 永久属性 不可修改
 */
    P: _Cls_Points = new _Cls_Points();
    /**
     * 技能列表
     */
    skills_body: SKILL[] = [];
    /**
     * 普通装备
     * 暂定6个
     */
    equip_ordinary: (equip | undefined)[] = [];
    pets: pet[] = [];
    createCfg!: any;
    _score: number = 0

    constructor() {

    }
    dbsave() {
        let obj: any = {}
        for (const key in this) {
            if (Object.prototype.hasOwnProperty.call(this, key)) {
                if (typeof (this[key]) == 'function') {
                    continue;
                }
                if (typeof (this[key]) == 'number' && !this[key]) {
                    continue;
                }
                if (!key.startsWith('_')) {
                    obj[key] = app.sanitizeObject(this[key]);
                }
            }
        }
        return obj
    }
    getMsgAttTpl(): { template: template, data: any } {

        return { template: template.none, data: {} }
    }
    getPets() {
        return this.pets;
    }
    getScore() {
        let score = 0;
        score += this._attributes.getScore();
        for (let i = 0; i < this.equip_ordinary.length; i++) {
            const element = this.equip_ordinary[i];
            if (!element) {
                continue;
            }
            score += element.getScore();
        }
        for (let i = 0; i < this.skills_body.length; i++) {
            const element = this.skills_body[i];
            score += element.score;
        }
        return score;
    }
    /**
     * 增加宠物
     */
    addPet(body: pet) {
        this.pets.push(body);
        body.set_Master(this)
    }
    init() {

        // 血统
        this.update_attributes();


        this.sk_trigger(EffectCondition.auto_附带即生效, [this])
        this._init = true;
    }
    getBag(): any {
        return undefined
    }
    get_Master(): baseBody {
        return this;
    }
    get_job_cfg() {
        let job_desc = app.xlsxCfgMap.get(xlsxCfgNames.血统表)?.get(this.Job_id);

        return job_desc
    }
    /**
   * 输出血统面板
   */
    get_panel_job(): Tpl_panel_job {
        let _job_cfg = this.get_job_cfg()
        let tpl: Tpl_panel_job = {
            title_style: '',
            type: _job_cfg.name,
            style_id: this.style_id,
            points: this.Job.getMultiple(this.Job_leve.num),
            leve: this.Job_leve
        };
        return tpl;
    }
    async sendMsg(tel: template, data?) {
        logger.debug(`[msg-${this.name}]${data}`)
    }
    /**
     * 血统资质
     * @param id 
     * @param add 额外百分百
     * @returns 
     */
    reset_job(id: string = this.Job_id, add = 0) {
        this.Job_id = id;
        let obj = {
            a: 0,
            b: 0,
            c: 0,
            d: 0
        };
        let total = app.random(100, 200 + 200 * add);
        let score = 0;
        let point = app.randomGroupPoint(total, 4)
        let idx = 0;
        for (const key in obj) {
            obj[key] = point[idx]
            score += point[idx];
            idx += 1;
        }
        this.Job.reset(obj);
        return score
    }
    /**
     * 输出天赋面板
     */
    get_panel_talent(): Tpl_panel_talent {
        let cfg = app.xlsxCfgMap.get(xlsxCfgNames.天赋表)?.get(this.Talent_id) as any;
        let tpl: Tpl_panel_talent = {
            title_style: 'none',
            name: cfg.name,
            style_id: cfg.styles[app.random(0, cfg.styles.length - 1)],
            leve: this.Talent_leve,
            points: this.Talent,
            max_points: this.Talent
        }
        return tpl
    }

    /**
     * 
     * @param add 额外增加百分比
     * @returns 
     */
    reset_talent(id?: string, add: number = 0) {
        let randomValues: number[] = [];
        let sum = 0;
        let max = app.generateRandom(10, 250 + (250 * add / 100)) / 100;
        while (sum < max && randomValues.length < 4) {
            const randomNum = app.generateRandom(0, 2 * 100) / 100;
            if (sum + randomNum <= max) { // 只有在总和小于2时才添加随机数
                randomValues.push(randomNum);
                sum += randomNum;
            }
        }

        // 将随机数组转换为对象格式
        const randomKey = {
            a: randomValues[0] || 0,
            b: randomValues[1] || 0,
            c: randomValues[2] || 0,
            d: randomValues[3] || 0
        };

        this.Talent_id = id || this.Talent_id;
        this.Talent.reset(randomKey);

        const score = randomValues.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
        return score
    }
    setSelectSkill(name: string) {
        this._selectSkill = name;
    }
    getSelectSkill() {
        return this._selectSkill;
    }
    getAllSkills() {
        let list = [...this.getSkill_body(), ...this.getSkill_equip()];
        for (let i = 0; i < list.length; i++) {
            const element = list[i];
            try {
                element.resetParent(this)
            } catch (error) {
                debugger
            }
        }
        return list;
    }
    getSkill_body() {
        return this.skills_body;
    }
    getSkill_equip() {
        let list: SKILL[] = [];
        for (let i = 0; i < this.equip_ordinary.length; i++) {
            const element = this.equip_ordinary[i];
            if (!element) {
                continue;
            }
            list.push(...element.skills)
        }
        return list
    }


    addExp(num: number) {
        const limit_pet = 10;
        const limit_sk = 1;
        const limit_equip = 1;
        const limit_talent = 1;
        const limit_body = 10;
        const limit_job = 1;
        let shareCont = limit_body;
        shareCont += limit_talent;
        const sks = this.getAllSkills();
        shareCont += sks.length * limit_sk;
        const equips = this.equip_ordinary.filter((e) => { if (e) { return e } }) as equip[];
        shareCont += equips.length * limit_equip;
        const pets = this.getPets();
        shareCont += pets.length * limit_pet;
        const shareExp = num / shareCont;

        for (let i = 0; i < pets.length; i++) {
            const element = pets[i];
            element.addExp(shareExp * limit_pet)
        }
        for (let i = 0; i < sks.length; i++) {
            const element = sks[i];
            element.addExp(shareExp * limit_sk)
        }
        for (let i = 0; i < equips.length; i++) {
            const element = equips[i];
            element.addExp(shareExp * limit_equip)
        }
        app.leveAddExp(shareExp * limit_talent, this.Talent_leve, this.upLeve_talent);
        app.leveAddExp(shareExp * limit_job, this.Job_leve, this.upLeve_job);
        app.leveAddExp(shareExp * limit_body, this.leve, this.upLeve);
    }
    private upLeve_talent = () => {
        this.Talent_leve.num += 1;
        this.Talent_leve.max = app.random(this.Talent_leve.num * 180000, this.Talent_leve.num * 270000);
        return true;
    }
    private upLeve_job = () => {
        this.Job_leve.num += 1;
        this.Job_leve.max = app.random(this.Job_leve.num * 30000, this.Job_leve.num * 90000);
        return true;
    }
    upLeve = () => {
        // if (this.leve.num >= this.getLeveLock()) {
        //     return;
        // }
        this.leve.num += 1;
        this.leve.max = this.leve.num * 100;
        return true
    }
    active() {
        const spaceTime = Math.floor((Date.now() - this._lastActiveTime) / 1000)
        this._lastActiveTime = Date.now();
        // 单位激活  查看时  读取属性时
        if (this.is_die()) {
            return;
        }
        if (spaceTime <= 0) {
            return;
        }

        body_tool.add_hp(this, {
            use_uuid: "0",
            use_name: "自身",
            sk_name: "生命恢复",
            group: group.主场,
            type: EffectType.恢复目标生命值,
            val: this._attributes.Hp_res * spaceTime
        })
        this.tool_changeMp({
            use_uuid: "0",
            use_name: "自身",
            sk_name: "魔法恢复",
            group: group.主场,
            type: EffectType.恢复目标生命值,
            val: this._attributes.Mp_res * spaceTime
        })
        for (let i = 0; i < this.pets.length; i++) {
            const element = this.pets[i];
            element.active();
        }

    }
    /**
     * 返回面板属性
     * @returns 
     */
    get_panelPoints() {
        let p = new _Cls_Points();
        p.add(this.P);
        try {
            p.add(this.Job.getMultiple(this.Job_leve.num));
        } catch (error) {
            debugger;
        }

        p.add(this.Talent.getMultiple(this.Talent_leve.num * this.leve.num));
        let equipArry = this.equip_ordinary;
        for (let index = 0; index < equipArry.length; index++) {
            const e = equipArry[index];
            if (!e) {
                continue;
            }
            // p.add(e.getPoints());
        }
        p.add(this._buffs.P)
        return p
    }
    update_attributes() {
        console.log(this.name, '更新属性')
        // 一级属性加上装备属性
        this._attributes.clearAll();

        this._attributes.Calls_cont = 1;
        let equipArry = this.equip_ordinary;
        for (let index = 0; index < equipArry.length; index++) {
            const e = equipArry[index];
            if (!e) {
                continue;
            }
            this._attributes.add(e.getAttributes())
        }

        // 根据等级额外附加生命值
        this._attributes.add({
            Hp_Max: this.leve.num * 5 * app.getAttVaule('Hp_Max'),
        })

        this._attributes.add(this.get_panelPoints().cover2Att())
        // TODO:计算buff 属性点加成
        this._attributes.add(this._buffs.att)
    }
    /**
   * 
   * @param cfg 
   * 记录创建配置
   */
    setCreateCfg(cfg: any) {
        this.createCfg = JSON.parse(JSON.stringify(cfg));
    }
    set_Cfg(data: CreateBody_base) {
        this.name = data.name;
        this.P = new _Cls_Points(data.Points);
        this.leve.num = data.leve;
        this.Talent_id = data.Talent;
        this.Talent_leve.num = data.Talent_leve;
        this.Job_id = data.Job;

        this.Job_leve.num = data.Job_leve;
        this.style_id = data.style_id;
        for (let index = 0; index < data.sk_actives.length; index++) {
            const element = data.sk_actives[index];
            this.addSkill(new SKILL(element))
        }
        this.reset_talent(this.Talent_id)
        this.reset_job(this.Job_id);
    }
    /**
     * 设置单位类型
     * @param type 
     */
    setBodyType(type: string) {
        this._bodyType = type;
    }
    getBodyType() {
        return this._bodyType;
    }



    getPosition() {
        return this._position as cell;
    }
    // 销毁
    destroy() {
        const sks = this.getAllSkills();
        for (let i = 0; i < sks.length; i++) {
            const element = sks[i];
            element.destroy();
        }
        for (let i = 0; i < this.pets.length; i++) {
            const element = this.pets[i];
            element.destroy();
        }
        // this.del_battle();
        if (this._position) {
            this.setPosition(undefined, true)
        }
        for (const key in this) {
            (this[key] as any) = undefined;
        }
    }
    setPosition(cell?: cell, force?: boolean) {
        if (this._position) {
            this._position.del(this, force);
        }
        this._position = cell;
        if (cell) {
            cell.add(this);
        }
    }
    read_key(k: string) {
        let val = 0;
        let buffVal = 0;
        switch (k) {
            case '无':
                break;
            case '力量':
                // 读取buff 附加力量
                buffVal = this._buffs.getVal(BuffEffect.力量)
                val = this.P.a + buffVal;
                break;
            case '等级':
                val = this.leve.num;
                break;
            case '当前生命':
                val = this.Hp_now;
                break;
            case '物理攻击':
                val = app.random(this._attributes.Physical_Attack_min, this._attributes.Physical_Attack_max)
                break;
            case '魔法攻击':
                val = app.random(this._attributes.Magic_Attack_min, this._attributes.Magic_Attack_max)
                break;
            case '物理防御':
                val = this._attributes.Physical_defense
                break;
            default:
                break;
        }
        return val;
    }

    /**
     * 测试
     * 0 默认自身技能
     * 1 job 血统技能
     */
    addSkill(sk: SKILL) {
        this.skills_body.push(sk);
        try {
            sk.resetParent(this);
        } catch (error) {
            debugger
        }
        if (this._init) {
            this.sk_trigger(EffectCondition.auto_附带即生效, [this])
        }
    }
    /**
     * 
     * @param idx 数组下标
     */
    delSkill(idx: number) {
        const deletedSkill = this.skills_body.splice(idx, 1)[0];
        deletedSkill.destroy();
    }
    /**
     * 触发特定条件
     */
    sk_trigger(condition: EffectCondition, bodys: baseBody[]) {
        let list = this.getAllSkills()
        for (let index = 0; index < list.length; index++) {
            const element = list[index];
            if (element.type == SK_type.被动技能) {
                element.autoUse(condition, bodys)
            }
        }
    }
    /**
     * 测试
     */
    set_group(g: group) {
        this._group = g;
    }
    set_battle(battle: battlefield) {
        this._battleArea = battle;
    }
    del_battle() {
        this._battleArea = undefined;
    }
    set_hasDecided(b: number) {
        this._hasDecided = b;
    }
    get_group() {
        return this._group;
    }
    get_hasDecided() {
        return this._hasDecided;
    }
    get_battle() {
        if (!this._battleArea?.id) {
            // try {
            //     this._battleArea?.destroy();
            // } catch (error) {
            this._battleArea = undefined;
            // }
        }
        return this._battleArea
    }
    is_die() {
        return this.Hp_now <= 0;
    }
    getBar() {
        return this.Hp_now / this._attributes.Hp_Max;
    }
    /**
     * 复活
     */
    res_life(log: battle_logNum) {
        if (log.val == -1) {
            this.Hp_now = this._attributes.Hp_Max;
            log.val = 1;
            return;
        }
        const val = log.val as number;
        this.Hp_now += val;
        if (this.Hp_now > this._attributes.Hp_Max) {
            this.Hp_now = this._attributes.Hp_Max;
        }
    }


    tool_changeMp(log: battle_logNum) {
        const val = log.val as number;
        if (this.Mp_now + val > this._attributes.Mp_Max) {
            log.val = this._attributes.Mp_Max - this.Mp_now;
            this.Mp_now = this._attributes.Mp_Max
        } else if (this.Mp_now + val < 0) {
            this.Mp_now = 0;
        } else {
            this.Mp_now += val;
        }
    }
    forever_addHpMax(n: number) {
        this.P.add({ a: n });
    }
    addBuff(bf: buff_item) {
        this._buffs.addBuff(bf);
    }
    del_buff(buff_id: string) {
        this._buffs.delBuff(buff_id);
    }
    getBuffVal(buff_effect: BuffEffect) {
        return this._buffs.getVal(buff_effect)
    }
    getBuff_effect(buff_effect: BuffEffect) {
        return this._buffs.getBuff(buff_effect)
    }
    on_battleSelect() {
        let area = this.get_battle() as battlefield;
        if (!area) {
            return;
        }
        setTimeout(() => {
            this.set_hasDecided(area.round);
            area.on_battleSelect(this);
        }, 15000)
    }
}